#include "widget.h"
#include "ui_widget.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDesktopServices>


Widget::Widget(QTcpSocket *tcpSocket, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , tcpSocket(tcpSocket)
    , alternateTcpSocket(new QTcpSocket(this))
    , useAlternateServer(false)
    , alternateServerIP("127.0.0.1") // 设置备用服务器IP
    , alternateServerPort(8888) // 设置备用服务器端口
    , currentPage(1)
    , itemsPerPage(5)
    , maxPage(0)
    , recommendTimer(new QTimer(this))
{
    ui->setupUi(this);
    setWindowTitle("SearchEngine");
    if (!tcpSocket) {
        // 处理空的 tcpSocket 情况
        QMessageBox::critical(this, "连接错误", "未能获取有效的 TCP 连接！");
        this->close();
        return;
    }

    // 连接成功后的信号槽
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot()));
    ui->recommendListWidget->hide();
    // 其他信号槽连接
    connect(ui->receiveEdit, &QTextBrowser::anchorClicked, this, &Widget::handleLinkClicked);
    connect(ui->sendEdit, &QLineEdit::textChanged, this, &Widget::keyWordRecommend);
    connect(ui->recommendListWidget, &QListWidget::itemClicked, this, &Widget::do_recommendItem_clicked);

    // 设置QTimer
    recommendTimer->setSingleShot(true);
    connect(recommendTimer, &QTimer::timeout, this, &Widget::sendRecommendRequest);

    // 连接切换按钮的信号槽
    connect(ui->switchServerButton, &QPushButton::clicked, this, &Widget::switchRecommendServer);

    // 连接备用服务器的 readyRead 信号槽
    connect(alternateTcpSocket, &QTcpSocket::readyRead, this, &Widget::readyReadAlternate_Slot);

    // 连接备用服务器
    connectAlternateServer();
}

void Widget::connectAlternateServer()
{
    alternateTcpSocket->connectToHost(alternateServerIP, alternateServerPort);
    if (!alternateTcpSocket->waitForConnected(3000)) {
        QMessageBox::critical(this, "连接错误", "无法连接到备用服务器！");
    }
}



Widget::~Widget()
{
    delete ui;
    if (tcpSocket) {
        tcpSocket->disconnectFromHost();
        tcpSocket->deleteLater();
    }
    if (alternateTcpSocket) {
        alternateTcpSocket->disconnectFromHost();
        alternateTcpSocket->deleteLater();
    }
}

void Widget::connected_Slot()
{
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot()));
}

void Widget::readyRead_Slot()
{
    static QByteArray buffer;
    static size_t expectedLength = 0;

    while (tcpSocket->bytesAvailable()) {
        if (expectedLength == 0) {
            // 读取长度信息
            if (tcpSocket->bytesAvailable() < sizeof(size_t)) {
                return; // 等待更多数据到来
            }
            char lengthBuffer[sizeof(size_t)];
            tcpSocket->read(lengthBuffer, sizeof(size_t));
            expectedLength = *reinterpret_cast<size_t*>(lengthBuffer);
        }

        if (tcpSocket->bytesAvailable() < expectedLength) {
            return; // 等待更多数据到来
        }

        buffer.append(tcpSocket->read(expectedLength));
        expectedLength = 0;

        QJsonDocument doc = QJsonDocument::fromJson(buffer);
        buffer.clear();

        if (!doc.isObject()) {
            return;
        }

        QJsonObject jsonObj = doc.object();
        int msgID = jsonObj["msgID"].toInt();
        if (msgID == 1) {
            ui->recommendListWidget->clear(); // 清空之前的推荐词
            QJsonArray keywords = jsonObj["msg"].toArray();
            for (const QJsonValue &value : keywords) {
                QString keyword = value.toString();
                ui->recommendListWidget->addItem(keyword); // 添加推荐词到列表
            }
            if (keywords.size() > 0) {
                ui->recommendListWidget->show(); // 显示推荐词列表
                ui->recommendListWidget->raise(); // 置于顶层
            }
        } else if (msgID == 2) {
            ui->recommendListWidget->hide();
            maxPage = jsonObj["maxPage"].toInt();
            searchResults = jsonObj["files"].toArray();
            queryWords = jsonObj["queryWords"].toArray();
            displaySearchResults();
        } else {
            ui->receiveEdit->setHtml("<p style='color:orange;'>Unexpected msgID: " + QString::number(msgID) + "</p>");
        }
    }
}

void Widget::readyReadAlternate_Slot()
{
    static QByteArray buffer;
    static size_t expectedLength = 0;

    while (alternateTcpSocket->bytesAvailable()) {
        if (expectedLength == 0) {
            // 读取长度信息
            if (alternateTcpSocket->bytesAvailable() < sizeof(size_t)) {
                return; // 等待更多数据到来
            }
            char lengthBuffer[sizeof(size_t)];
            alternateTcpSocket->read(lengthBuffer, sizeof(size_t));
            expectedLength = *reinterpret_cast<size_t*>(lengthBuffer);
        }

        if (alternateTcpSocket->bytesAvailable() < expectedLength) {
            return; // 等待更多数据到来
        }

        buffer.append(alternateTcpSocket->read(expectedLength));
        expectedLength = 0;

        QJsonDocument doc = QJsonDocument::fromJson(buffer);
        buffer.clear();

        if (!doc.isObject()) {
            return;
        }

        QJsonObject jsonObj = doc.object();
        int msgID = jsonObj["msgID"].toInt();
        if (msgID == 1) {
            ui->recommendListWidget->clear(); // 清空之前的推荐词
            QJsonArray keywords = jsonObj["msg"].toArray();
            for (const QJsonValue &value : keywords) {
                QString keyword = value.toString();
                ui->recommendListWidget->addItem(keyword); // 添加推荐词到列表
            }
            if (keywords.size() > 0) {
                ui->recommendListWidget->show(); // 显示推荐词列表
                ui->recommendListWidget->raise(); // 置于顶层
            }
        } else {
            ui->receiveEdit->setHtml("<p style='color:orange;'>Unexpected msgID: " + QString::number(msgID) + "</p>");
        }
    }
}


void Widget::displaySearchResults()
{
    QString htmlContent;
    int totalItems = searchResults.size();

    int start = 0;
    int end = totalItems;

    for (int i = start; i < end; ++i) {
        QJsonObject fileObj = searchResults[i].toObject();
        QString title = fileObj["title"].toString();
        QString summary = fileObj["summary"].toString();
        QString url = fileObj["url"].toString();

        // 标记 summary 中的 queryWords，增加背景色
        for (const QJsonValue &value : queryWords) {
            QString queryWord = value.toString();
            summary.replace(queryWord, "<span style='color:red; background-color:yellow;'>" + queryWord + "</span>", Qt::CaseInsensitive);
        }

        htmlContent.append(
            "<div>"
            "<p><b>[标题]</b> <a href='" + url + "' style='color:green;'>" + title + "</a></p>"
            "<p><b>[摘要]</b> " + summary + "</p>"
            "<p><b>[链接]</b> <a href='" + url + "'>" + url + "</a></p>"
            "<hr/>"
            "</div>"
        );
    }

    htmlContent.append("<p>当前页码: " + QString::number(currentPage) + " / 总页码: " + QString::number(maxPage) + "</p>");

    ui->receiveEdit->setHtml(htmlContent);
}

void Widget::keyWordRecommend()
{
    if (ui->sendEdit->text().isEmpty()) {
        ui->recommendListWidget->hide();
        return;
    }

    recommendTimer->start(500);
}

void Widget::sendRecommendRequest()
{
    if (ui->sendEdit->text().isEmpty()) {
        ui->recommendListWidget->hide();
        return;
    }

    int query_id = 1;
    QString msg = ui->sendEdit->text();

    QJsonObject json;
    json["query_id"] = query_id;
    json["msg"] = msg;

    QJsonDocument doc(json);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact) + "\n";

    if (useAlternateServer) {
        alternateTcpSocket->write(jsonData);
    } else {
        tcpSocket->write(jsonData);
    }
}


void Widget::on_searchBt_clicked()
{
    searchResults = QJsonArray();
    currentPage = 1;
    ui->recommendListWidget->hide();
    sendSearchRequest(currentPage);
}

void Widget::sendSearchRequest(int page)
{
    int query_id = 2;
    QString msg = ui->sendEdit->text();

    QJsonObject json;
    json["query_id"] = query_id;
    json["msg"] = msg;
    json["pageNum"] = page;
    json["itemsPerPage"] = itemsPerPage;

    QJsonDocument doc(json);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact) + "\n";

    tcpSocket->write(jsonData);
}

void Widget::handleLinkClicked(const QUrl &url)
{
     QDesktopServices::openUrl(url);
}

void Widget::on_prevPageBt_clicked()
{
    if (currentPage > 1) {
        sendSearchRequest(--currentPage);
    }
}

void Widget::on_nextPageBt_clicked()
{
    if (currentPage < maxPage) {
        sendSearchRequest(++currentPage);
    }
}

void Widget::on_jumpBt_clicked()
{
    bool ok;
    int page = ui->pageEdit->text().toInt(&ok);
    if (ok) {
        if (page >= 1 && page <= maxPage) {
            currentPage = page;
            sendSearchRequest(page);
        } else {
            QMessageBox::warning(this, "页码错误", "页码不合法，请输入有效的页码！");
        }
    } else {
        QMessageBox::warning(this, "输入错误", "请输入有效的数字页码！");
    }
}

void Widget::handlePaginationLinks(const QUrl &url)
{
    if (url.fragment() == "prevPage") {
        on_prevPageBt_clicked();
    } else if (url.fragment() == "nextPage") {
        on_nextPageBt_clicked();
    } else {
        QDesktopServices::openUrl(url);
    }
}

void Widget::do_recommendItem_clicked(QListWidgetItem *item)
{
    QString keyword = item->text();

    // 临时断开信号连接
    disconnect(ui->sendEdit, &QLineEdit::textChanged, this, &Widget::keyWordRecommend);
    ui->sendEdit->setText(keyword);
    // 重新连接信号
    connect(ui->sendEdit, &QLineEdit::textChanged, this, &Widget::keyWordRecommend);

    on_searchBt_clicked(); // 发起搜索操作
}

void Widget::switchRecommendServer()
{
    useAlternateServer = !useAlternateServer; // 切换状态
    QString serverInfo = useAlternateServer ? "前缀匹配+预训练模型" : "最小编辑距离";
    QMessageBox::information(this, "切换关键词推荐模型", "当前使用的关键词推荐模型： " + serverInfo);
}


